﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Media;

namespace OpenLightGroup.Common
{
    /// <summary>
    /// Extensions for DependencyObject 
    /// </summary>
    public static class DependencyObjectExtensions
    {
           
        /// <summary>
        /// Returns the first parent in the Visual Tree that matches the specified type.
        /// </summary>
        /// <typeparam name="T">Type of parent to return.</typeparam>
        /// <param name="element"></param>
        /// <returns></returns>
        public static T ParentOfType<T>(this DependencyObject element) where T : DependencyObject
        {
            if (element == null)
                return default(T);

            while ((element = VisualTreeHelper.GetParent(element)) != null)
            {
                if (element is T)
                    return (T)element;
            }
            return null;
        }

        /// <summary>
        /// Returns the first child of the specified type.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static T ChildOfType<T>(this DependencyObject obj)
            where T : DependencyObject
        {
            return ChildOfType<T>(obj, null);
        }

        /// <summary>
        /// Returns the first child of the specified type with a matching name.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static T ChildOfType<T>(this DependencyObject obj, string name)
             where T : DependencyObject
        {
            return ChildrenOfType<T>(obj, name).FirstOrDefault();
        }

        /// <summary>
        /// Returns all children of the specified type.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static IEnumerable<T> ChildrenOfType<T>(this DependencyObject obj)
            where T : DependencyObject
        {
            return ChildrenOfType<T>(obj, null);
        }

        /// <summary>
        /// Returns all children of the specified type with matching names.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static IEnumerable<T> ChildrenOfType<T>(this DependencyObject obj, string name)
            where T : DependencyObject
        {
            if (obj == null)
            {
                 yield return null;
            }

            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                object child = VisualTreeHelper.GetChild(obj, i);

                //var rightWay = thisWay ? typeof(T).IsAssignableFrom(child.GetType()) : child is T;

                if (child is T && (String.IsNullOrEmpty(name) || ((FrameworkElement)child).Name == name))
                {
                    yield return (T)child;
                }

                var objects = ((DependencyObject)child).ChildrenOfType<T>(name);

                if (objects != null)

                    foreach (var childObjects in objects)
                        yield return childObjects;
            }

        }

    }
}
